; rdio.asm
; Byte I/O routines for FE3 RAM Disk
;
	.include "fe3def.inc"
	.include "rdglobal.inc"
	.include "rdmem.inc"
	.include "rdmain.inc"
	.include "rdcmd.inc"
	.include "rdrel.inc"
	_IN_RDIO = 1
	.include "rdio.inc"
	
	.segment "LDATA"
	
outinfo:	.tag FileInfo
ininfo:		.tag FileInfo
	
save_x:		.res 1
save_y:		.res 1
	
	.segment "LCODE"
	
;----------------------------------------------------------
; Bank RAM R/W 
;----------------------------------------------------------

; Writes a byte to SuperRAM
; INPUT:
;	A .......... byte to write
;	X .......... target bank
;	Y .......... source bank
;	(iowadr) ... target address
;	
io_write:	stx FE3_REG1		
@wcmd:		sta $FFFF
			sty FE3_REG1
			rts
iowadr = @wcmd+1

; Reads a byte from SuperRAM
; INPUT:
;	X .......... target bank
;	Y .......... source bank
;	(ioradr) ... target address
; OUTPUT:
;	A .......... byte read
;	
io_read:	stx FE3_REG1		
@rcmd:		lda $FFFF
			sty FE3_REG1
			rts
ioradr = @rcmd+1

;----------------------------------------------------------
; BASIN/GETIN hooks
;----------------------------------------------------------

; Read in full block
readblk:	php
			sei
			stx save_x
			lda FE3_REG1
			pha
			lda ininfo+FileInfo::bank
			sta FE3_REG1
			ldx ininfo+FileInfo::pos
rb_adr:		lda $FF00, x
			sta OUTBUF
			inx
			stx ininfo+FileInfo::pos
			bne done
			; next block
			sty save_y
			lda rb_adr+2
			jsr md_walk
			bcc @do_nxt
			; eof
			ldx #IO_MODE_READEOF
			stx ininfo+FileInfo::mode
			jsr io_setin
			lda #$40				; ST := EOF
			jsr $FE6A
			bne @doney
@do_nxt:	sta ininfo+FileInfo::bank
			sty ininfo+FileInfo::addr
			sty rb_adr+2
			cpx #0
			bne @doney
			; last block
			lda ininfo+FileInfo::losize
			beq @doney
			sty rt_adr+2
			ldx #IO_MODE_READTAIL
			stx ininfo+FileInfo::mode
			jsr io_setin
@doney:		ldy save_y
done:		pla
			sta FE3_REG1
			lda OUTBUF
			ldx save_x
			plp
			clc
			rts
			
; Read in last block
readtail:	php
			sei
			stx save_x
			lda FE3_REG1
			pha
			lda ininfo+FileInfo::bank
			sta FE3_REG1
			ldx ininfo+FileInfo::pos
rt_adr:		lda $FF00, x
			sta OUTBUF
			inx
			stx ininfo+FileInfo::pos
			cpx ininfo+FileInfo::losize
			bcc done
			; EOF
			ldx #IO_MODE_READEOF
			stx ininfo+FileInfo::mode
			jsr io_setin
			lda #$40				; ST := EOF
			jsr $FE6A
			bne done

; Read after EOF
readeof:	lda #13
			sec
			rts
			
; Read directory
readdir:	php
			sei
			lda FE3_REG1
			pha
			lda #CODE_BANK | SUPER_RAM_MODE
			sta FE3_REG1
			jsr rd_adr
rstbnkrd:	pla
			sta FE3_REG1
			lda OUTBUF
			plp
			clc
			rts

	.segment "CODE"

rd_adr:		lda $FFFF
			sta OUTBUF
			inc ininfo+FileInfo::dirptr
			inc rd_adr+1
			bne @nohi
			inc ininfo+FileInfo::dirptr+1
			inc rd_adr+2
@nohi:		lda ininfo+FileInfo::dirptr+1
			cmp ininfo+FileInfo::addr
			bne @done
			lda ininfo+FileInfo::dirptr
			cmp ininfo+FileInfo::bank
			bne @done
			; EOF
			ldx #IO_MODE_READEOF
			stx ininfo+FileInfo::mode
			jsr io_setin
			lda #$40				; ST := EOF
			jsr $FE6A
@done:		rts
	
	.segment "LCODE"
			
; Read output file
readerr:	lda #ERR_NOT_INPUT_FILE
			sec
			rts

; Read command channel
readcmd:	php
			sei
			lda FE3_REG1
			pha
			lda #CODE_BANK | SUPER_RAM_MODE
			sta FE3_REG1
			jsr cmd_read
			sta OUTBUF
			jmp rstbnkrd

;----------------------------------------------------------
; BSOUT hooks
;----------------------------------------------------------

; Write first byte
writefrst:	php
			sei
			sta OUTBUF
			lda FE3_REG1
			pha
			stx save_x
			sty save_y
			jsr md_alloc
			cmp #0
			bne @goon
			pla
			sta FE3_REG1
			lda #ERR_TOO_MANY_FILES
			plp
			sec
			rts
@goon:		sta outinfo+FileInfo::bank
			sty outinfo+FileInfo::addr
			sty wr_adr+2
			; update blocks
			inc outinfo+FileInfo::blocks
			bne @skphi
			inc outinfo+FileInfo::blocks+1
@skphi:		; update dir entry
			lda #CODE_BANK | SUPER_RAM_MODE
			sta FE3_REG1
			jsr upd_dir_ptr
			; update out mode
			ldx #IO_MODE_WRITENEXT
			stx outinfo+FileInfo::mode
			jsr io_setout
			; write byte
			lda outinfo+FileInfo::bank
			sta FE3_REG1
			ldx #0
			jmp do_write

; Write all other bytes
writenext:	php
			sei
			sta OUTBUF
			lda FE3_REG1
			pha
			stx save_x
			sty save_y
			; write byte
			lda outinfo+FileInfo::bank
			sta FE3_REG1
			ldx outinfo+FileInfo::losize
			bne do_write
			; next block
			ldy outinfo+FileInfo::addr
			jsr md_addblk
			bcc @blkok
			pla
			sta FE3_REG1
			lda #ERR_TOO_MANY_FILES
			plp
			sec
			rts
@blkok:		sta outinfo+FileInfo::bank
			sta FE3_REG1
			sty outinfo+FileInfo::addr
			sty wr_adr+2
			inc outinfo+FileInfo::blocks
			bne @skphi
			inc outinfo+FileInfo::blocks+1
@skphi:		ldx outinfo+FileInfo::losize
do_write:	lda OUTBUF
wr_adr:		sta $FF00, x
			inx
			stx outinfo+FileInfo::losize
			pla
			sta FE3_REG1
			ldx save_x
			ldy save_y
			plp
			clc
			rts
			
; Write to input file 			
writeerr:	lda #ERR_NOT_OUTPUT_FILE
			sec
			rts

; Write to command channel
writecmd:	sta OUTBUF
			php
			sei
			lda FE3_REG1
			pha
			lda #CODE_BANK | SUPER_RAM_MODE
			sta FE3_REG1
			lda OUTBUF
			jsr cmd_write
			pla
			sta FE3_REG1
			plp
			clc
			rts

;----------------------------------------------------------
; Prepare I/O 
;----------------------------------------------------------

	.segment "CODE"

prpnul:		rts

prprdblk:	lda ininfo+FileInfo::addr
			sta rb_adr+2
			rts
			
prprdtl:	lda ininfo+FileInfo::addr
			sta rt_adr+2
			rts
			
prprddir:	lda ininfo+FileInfo::dirptr
			sta rd_adr+1 
			lda ininfo+FileInfo::dirptr+1
			sta rd_adr+2
			rts

prpwrfrst:	
			rts
			
prpwrnxt:	lda outinfo+FileInfo::addr
			sta wr_adr+2
			rts
			
;----------------------------------------------------------
; Set-up I/O 
;----------------------------------------------------------

	.segment "TABLE"
	
funptr:		.res 2

	.segment "CODE"
	
; Call funptr
;
call_fn:	jmp (funptr)

; Init I/O vectors
;
io_init:	pha
			lda INPUT_VECTOR
			sta imode_lo
			lda INPUT_VECTOR+1
			sta imode_hi
			lda GETIN_VECTOR
			sta gmode_lo
			lda GETIN_VECTOR+1
			sta gmode_hi
			lda OUTPUT_VECTOR
			sta omode_lo
			lda OUTPUT_VECTOR+1
			sta omode_hi
			lda #$FF
			sta ininfo+FileInfo::index
			sta outinfo+FileInfo::index
			pla
			rts

; Prepare input mode (0..6)
; INPUT:
;	X ... mode
;
io_prepin:	pha
			lda setin_lo, x
			sta funptr
			lda setin_hi, x
			sta funptr+1
			jsr call_fn
			pla	
			rts
			
; Prepare output mode (0..6)
; INPUT:
;	X ... mode
;
io_prepout:	pha
			lda setout_lo, x
			sta funptr
			lda setout_hi, x
			sta funptr+1
			jsr call_fn
			pla	
			rts

	.segment "LCODE"

; Set output mode (0..6)
; INPUT:
;	X ... mode
;
io_setout:	pha
			lda omode_lo, x
			sta OUTPUT_VECTOR
			lda omode_hi, x
			sta OUTPUT_VECTOR+1
			pla
			rts

; Set input mode (0..6)
; INPUT:
;	X ... mode
;
io_setin:	pha
			lda imode_lo, x
			sta INPUT_VECTOR
			lda imode_hi, x
			sta INPUT_VECTOR+1
			lda gmode_lo, x
			sta GETIN_VECTOR
			lda gmode_hi, x
			sta GETIN_VECTOR+1
			pla
			rts

	.segment "LDATA"
	
imode_lo:	.byte 0, <readblk, <readtail, <readeof, <readdir, <readerr, <readerr, <readcmd, <readcmd
imode_hi:	.byte 0, >readblk, >readtail, >readeof, >readdir, >readerr, >readerr, >readcmd, >readcmd

gmode_lo:	.byte 0, <readblk, <readtail, <readeof, <readdir, <readerr, <readerr, <readcmd, <readcmd
gmode_hi:	.byte 0, >readblk, >readtail, >readeof, >readdir, >readerr, >readerr, >readcmd, >readcmd

omode_lo:	.byte 0, <writeerr, <writeerr, <writeerr, <writeerr, <writefrst, <writenext, <writecmd, <writecmd 
omode_hi:	.byte 0, >writeerr, >writeerr, >writeerr, >writeerr, >writefrst, >writenext, >writecmd, >writecmd

	.segment "RODATA"

setin_lo:	.byte <prpnul, <prprdblk, <prprdtl, <prpnul, <prprddir, <prpnul, <prpnul, <cmd_chkin, <rel_chkin
setin_hi:	.byte >prpnul, >prprdblk, >prprdtl, >prpnul, >prprddir, >prpnul, >prpnul, >cmd_chkin, >rel_chkin

setout_lo:	.byte <prpnul, <prpnul, <prpnul, <prpnul, <prpnul, <prpwrfrst, <prpwrnxt, <cmd_ckout, <rel_ckout
setout_hi:	.byte >prpnul, >prpnul, >prpnul, >prpnul, >prpnul, >prpwrfrst, >prpwrnxt, >cmd_ckout, >rel_ckout

			